home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Libris Britannia 4
/
science library(b).zip
/
science library(b)
/
DJGPP
/
CBGRX103.ZIP
/
contrib
/
libgrx
/
src
/
thicklne.c
< prev
next >
Wrap
Text File
|
1993-12-06
|
6KB
|
230 lines
/**
** THICKLNE.C
**
** Copyright (C) 1992, Csaba Biegl
** 820 Stirrup Dr, Nashville, TN, 37221
** csaba@vuse.vanderbilt.edu
**
** This file is distributed under the terms listed in the document
** "copying.cb", available from the author at the address above.
** A copy of "copying.cb" should accompany this file; if not, a copy
** should be available from where this file was obtained. This file
** may not be distributed without a verbatim copy of "copying.cb".
** You should also have received a copy of the GNU General Public
** License along with this program (it is in the file "copying");
** if not, write to the Free Software Foundation, Inc., 675 Mass Ave,
** Cambridge, MA 02139, USA.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**/
#include "grx.h"
#include "libgrx.h"
#include "clipping.h"
#include "thicklne.h"
void _GrBuildCustomLineData(GrLineOption *opt,GrCustomLineData *where)
{
int total,ii;
where->opt = *opt;
if(opt->lno_pattlen > 1) {
for(total = 0,ii = opt->lno_pattlen; --ii >= 0; total += opt->lno_dashpat[ii]);
where->total_pattlen = total;
where->next_sect = 0;
where->cursect_left = 0;
where->drawn_sect = FALSE;
}
else where->total_pattlen = 0;
}
extern void _GrDoCustomSegment(int x1,int y1,int x2,int y2,void *arg)
{
#define DIAG(x,y) ((x)*(x) + (y)*(y))
GrCustomLineData *dta = (GrCustomLineData *)arg;
int dx1,dy1,dx2,dy2; /* offsets to corner points of thick line segment */
int sx1,sx2,sy1,sy2,length; /* line segment length and end points */
int pts[4][2]; /* polygon corner points */
int dx = x2 - x1;
int dy = y2 - y1;
int wdt = dta->opt.lno_width;
int Xmajor = (IABS(dx) > IABS(dy)) ? TRUE : FALSE;
int done;
if(wdt > 1) {
int wsq = wdt * wdt;
if(dx == 0) {
dy2 = 0;
dx2 = wdt;
}
else if(dy == 0) {
dx2 = 0;
dy2 = wdt;
}
else if(Xmajor) {
dy1 = ((7 * wdt) / 10) - 1; /* at least !! (tangent is less than 45 deg) */
dx1 = -(dy1 * dy) / dx; /* scale according to slope */
for( ; ; ) {
dy2 = dy1 + 1;
dx2 = -(dy2 * dy) / dx;
if(DIAG(dx2,dy2) > wsq) break;
dx1 = dx2;
dy1 = dy2;
}
if((DIAG(dx2,dy2) - wsq) > (wsq - DIAG(dx1,dy1))) {
dx2 = dx1;
dy2 = dy1;
}
}
else {
dx1 = ((7 * wdt) / 10) - 1; /* at least !! (tangent is more than 45 deg) */
dy1 = -(dx1 * dx) / dy; /* scale according to slope */
for( ; ; ) {
dx2 = dx1 + 1;
dy2 = -(dx2 * dx) / dy;
if(DIAG(dx2,dy2) > wsq) break;
dx1 = dx2;
dy1 = dy2;
}
if((DIAG(dx2,dy2) - wsq) > (wsq - DIAG(dx1,dy1))) {
dx2 = dx1;
dy2 = dy1;
}
}
dx1 = dx2 >> 1;
dy1 = dy2 >> 1;
dx2 = dx1 - dx2;
dy2 = dy1 - dy2;
}
if((dta->total_pattlen == 0) || ((dx == 0) && (dy == 0))) {
if(wdt <= 1) {
(*dta->borderproc)(x1,y1,x2,y2,dta->fillarg);
return;
}
pts[0][0] = x1 + dx1;
pts[0][1] = y1 + dy1;
pts[1][0] = x1 + dx2;
pts[1][1] = y1 + dy2;
pts[2][0] = x2 + dx2;
pts[2][1] = y2 + dy2;
pts[3][0] = x2 + dx1;
pts[3][1] = y2 + dy1;
_GrScanConvexPoly(4,pts,
dta->is_XOR_color,
dta->pixelproc,
dta->borderproc,
dta->scanfillproc,
dta->fillarg
);
return;
}
sx1 = x1;
sy1 = y1;
done = FALSE;
while(!done) {
if((length = dta->cursect_left) == 0) do {
if(dta->next_sect == dta->opt.lno_pattlen) {
dta->next_sect = 0;
dta->drawn_sect = FALSE;
}
length = dta->opt.lno_dashpat[dta->next_sect++];
dta->drawn_sect ^= 1;
} while(length == 0);
else dta->cursect_left = 0;
if(Xmajor) {
if(dx < 0) {
if((sx2 = sx1 - length) <= x2) {
dta->cursect_left = x2 - sx2;
length = sx1 - (sx2 = x2);
done = TRUE;
}
else sx2++;
}
else {
if((sx2 = sx1 + length) >= x2) {
dta->cursect_left = sx2 - x2;
length = (sx2 = x2) - x1;
done = TRUE;
}
else sx2--;
}
sy1 = y1 + (((sx1 - x1) * dy) / dx);
sy2 = y1 + (((sx2 - x1) * dy) / dx);
}
else {
if(dy < 0) {
if((sy2 = sy1 - length) <= y2) {
dta->cursect_left = y2 - sy2;
length = sy1 - (sy2 = y2);
done = TRUE;
}
else sy2++;
}
else {
if((sy2 = sy1 + length) >= y2) {
dta->cursect_left = sy2 - y2;
length = (sy2 = y2) - y1;
done = TRUE;
}
else sy2--;
}
sx1 = x1 + (((sy1 - y1) * dx) / dy);
sx2 = x1 + (((sy2 - y1) * dx) / dy);
}
if(dta->drawn_sect && (length > 0)) {
if(wdt <= 1)
(*dta->borderproc)(sx1,sy1,sx2,sy2,dta->fillarg);
else {
pts[0][0] = sx1 + dx1;
pts[0][1] = sy1 + dy1;
pts[1][0] = sx1 + dx2;
pts[1][1] = sy1 + dy2;
pts[2][0] = sx2 + dx2;
pts[2][1] = sy2 + dy2;
pts[3][0] = sx2 + dx1;
pts[3][1] = sy2 + dy1;
_GrScanConvexPoly(4,pts,
dta->is_XOR_color,
dta->pixelproc,
dta->borderproc,
dta->scanfillproc,
dta->fillarg
);
}
}
if(Xmajor) {
if(dx < 0) sx1 -= length;
else sx1 += length;
}
else {
if(dy < 0) sy1 -= length;
else sy1 += length;
}
}
}
extern void _GrDoSingleCustomSegment(int x1,int y1,int x2,int y2,GrCustomLineData *dta)
{
int minx = x1,maxx = x2;
int miny = y1,maxy = y2;
MOUSE_FLAG;
SORT2(minx,maxx);
SORT2(miny,maxy);
if(dta->opt.lno_width > 1) {
minx -= dta->opt.lno_width;
maxx += dta->opt.lno_width;
miny -= dta->opt.lno_width;
maxy += dta->opt.lno_width;
}
CLIPSORTEDBOX(CURC,minx,miny,maxx,maxy);
MOUSE_BLOCK(CURC,minx,miny,maxx,maxy);
_GrDoCustomSegment(x1,y1,x2,y2,dta);
MOUSE_UNBLOCK();
}